#include "common.h"

#define BACK_LOG 10
#define BUFF_SIZE 1024

class TcpServer  
{
  public:
    TcpServer(const int port)
      :_port(port)
      ,_listenSock(-1)
    {}

    ~TcpServer()
    {
      if(_listenSock >= 0)
      {
        close(_listenSock);
      }
    }

    void InitServer()
    {
      // 1、创建套接字
      _listenSock = socket(AF_INET, SOCK_STREAM, 0);
      // 2、绑定套接字
      struct sockaddr_in local;
      memset(&local, 0, sizeof(local));
      local.sin_family = AF_INET;
      local.sin_port = htons(_port);
      local.sin_addr.s_addr = INADDR_ANY;
      bind(_listenSock, (struct sockaddr*)&local, sizeof(local));
      // 3、设置监听套接字
      listen(_listenSock, BACK_LOG);
    }

    // 服务客户端
    void Service(const int linkSock, const string& ip, const int port)
    {
      char buff[BUFF_SIZE];

      while(1)
      {
        ssize_t size = read(linkSock, buff, sizeof(buff)-1);
        if(size > 0)
        {
          buff[size] = 0;
          cout<<'['<<ip<<':'<<port<<"]# "<<buff<<endl;
          write(linkSock, buff, size);
        }
        else if(size == 0)
        {
          cout<<"client close!"<<endl;
          break;
        }
        else 
        {
          cerr<<"read error"<<endl;
          break;
        }
      }
      // 服务完成后要记得关闭该连接套接字
      close(linkSock);
    }

    // 启动服务器
    void LoopServer()
    {
      struct sockaddr_in peer;
      memset(&peer, 0, sizeof(peer));
      socklen_t len = sizeof(peer);

      // 不断地监听获取客户端的连接请求
      while(1)
      {
        int linkSock = accept(_listenSock, (struct sockaddr*)&peer, &len);
        // 若该套接字监听失败，继续监听下一个套接字即可
        if(linkSock == -1)
        {
          cout<<"accept error, continue next link"<<endl;
          continue;
        }
        int port = ntohs(peer.sin_port);
        string ip = inet_ntoa(peer.sin_addr);
        cout<<"get a new link, sockfd is "<<linkSock<<endl;
        // 连接成功后，为客户端提供服务
        Service(linkSock, ip, port);
      }
    }

  private:
    int _port;
    int _listenSock;
};
